<?php

namespace Desktopd\PlatformTools;

use DateTime;
use DateTimeZone;


/*
	TODO: Deprecate this class and refactor logging
*/

class Log {
	const EMERG = 0; // system is unusable
	const EMERGENCY = self::EMERG;
	
	const ALERT = 1; // action must be taken immediately
	
	const CRIT = 2; // critical conditions
	const CRITICAL = self::CRIT;
	
	const ERR = 3; // error conditions
	const ERROR = self::ERR;
	
	const WARNING = 4; // warning conditions
	const WARN = self::WARNING;
	
	const NOTICE = 5; // normal, but significant, condition
	
	const INFO = 6; // informational message
	const INFORMATION = self::INFO;
	const INFORMATIONAL = self::INFO;
	
	const DEBUG = 7; // debug-level message
	const DBG = self::DEBUG;
	
	const DEBUG2 = 8; // debug-level message
	const DBG2 = self::DEBUG2;
	
	const UNKNOWN = PHP_INT_MAX;
	
	
	private static $logLevel = self::DEBUG;
	private static $logLevels = array(
		self::EMERG => 'emergency',
		self::ALERT => 'alert',
		self::CRIT => 'critical',
		self::ERR => 'error',
		self::WARNING => 'warning',
		self::NOTICE => 'notice',
		self::INFO => 'info',
		self::DEBUG => 'debug',
		self::DEBUG2 => 'debug2',
		self::UNKNOWN => '_unknown_log_level_'
	);
	
	private static $logFile = false;
	
	private static $consoleLogLevel = self::INFO;
	
	
	private function __construct () {} // this should never be used (but DO NOT DELETE THIS!)
	
	public static function setLogFile ($file) {
		if (file_exists($file)) {
			if (!is_file($file)) return false;
			if (!is_writable($file)) return false;
		} else {
			if (!is_writable(dirname($file))) return false;
		}
		
		self::$logFile = $file;
		return true;
	}
	
	public static function archiveTo ($archive) {
	    if (self::$logFile === false)  return false;
	    if (!file_exists(self::$logFile)) return false;
	    
	    if (file_exists($archive)) {
			if (!is_writable($archive)) return false;
		} else {
			if (!is_writable(dirname($archive))) return false;
		}
		
		return rename(self::$logFile, $archive);
	}
	
	private static function processLogLevel ($level) {
		$level = "$level";
		if (!is_numeric($level)) $level = self::UNKNOWN;
		if ($level > 8 || $level < 0) $level = self::UNKNOWN;
		return round(max(0, min(8, $level)));
	}
	
	private static function logLevelToString ($level) {
		return self::$logLevels[self::processLogLevel($level)];
	}
	
	public static function setLogLevel ($level) {
	    return self::logLevelToString(
	        self::$logLevel = self::processLogLevel($level)
	    );
	}
	
	public static function getLogLevel ($isString = true) {
	    return $isString ?
	        self::logLevelToString(self::$logLevel) :
	        self::$logLevel;
	}
	
	public static function setConsoleLogLevel ($level) {
	    return self::logLevelToString(
	        self::$consoleLogLevel = self::processLogLevel($level)
	    );
	}
	
	public static function getConsoleLogLevel ($isString = true) {
	    return $isString ?
	        self::logLevelToString(self::$consoleLogLevel) :
	        self::$consoleLogLevel;
	}
	
	public static function log ($message, $level = self::INFO) {
		$level = self::processLogLevel($level);
		$levelName = self::logLevelToString($level);
		$time = microtime();
		$u = substr($time, 2, 6);
		$s = explode(' ', $time)[1];
		$date = DateTime::createFromFormat('U u', "$s $u", new DateTimeZone('UTC'));
		$date = $date->format('d M Y H:i:s.u \U\T\C');
		$str = "$date [$levelName] $message\n";
		
		if (self::$logFile !== false && $level <= self::$logLevel) {
			file_put_contents(self::$logFile, $str, LOCK_EX | FILE_APPEND);
		}
		
		if ($level <= self::$consoleLogLevel) {
			if (defined('STDERR') && is_resource(STDERR)) {
				fwrite(STDERR, $str);
			} else {
				@file_put_contents('php://stderr', $str);
			}
		}
		
		return true;
	}
	
	public static function getFileSize () {
	    if (!file_exists(self::$logFile)) return false;
	    return filesize(self::$logFile);
	}
	
}


// vim: ts=4 noet ai

